"""
配置历史管理
提供配置变更历史记录的创建、查询和管理功能
"""

import asyncio
import logging
from datetime import datetime
from typing import Dict, List, Optional, Any
from data_models.Config import ConfigChange, ConfigChangeType


class ConfigHistoryManager:
    """配置历史管理器"""

    def __init__(self, db_manager):
        self.db_manager = db_manager
        self.logger = logging.getLogger(__name__)

    async def record_change(self, change: ConfigChange) -> bool:
        """
        记录配置变更

        Args:
            change: 配置变更对象

        Returns:
            bool: 记录是否成功
        """
        try:
            query = """
                INSERT INTO config_history (
                    config_key, config_id, old_value, new_value,
                    change_type, changed_by, change_reason, ip_address, user_agent
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
            """

            await self.db_manager.execute_insert(query, (
                change.config_key,
                change.config_id,
                change.old_value,
                change.new_value,
                change.change_type.value,
                change.changed_by,
                change.change_reason,
                change.ip_address,
                change.user_agent
            ))

            self.logger.info(f"Recorded config change: {change.config_key} by {change.changed_by}")
            return True

        except Exception as e:
            self.logger.error(f"Failed to record config change: {e}")
            return False

    async def record_config_update(self, config_key: str, config_id: int,
                                 old_value: str, new_value: str,
                                 changed_by: str, change_reason: str = None,
                                 ip_address: str = None, user_agent: str = None) -> bool:
        """
        记录配置更新

        Args:
            config_key: 配置键名
            config_id: 配置项ID
            old_value: 旧值
            new_value: 新值
            changed_by: 操作人
            change_reason: 变更原因
            ip_address: IP地址
            user_agent: 用户代理

        Returns:
            bool: 记录是否成功
        """
        change = ConfigChange(
            config_key=config_key,
            config_id=config_id,
            old_value=old_value,
            new_value=new_value,
            change_type=ConfigChangeType.UPDATE,
            changed_by=changed_by,
            change_reason=change_reason,
            ip_address=ip_address,
            user_agent=user_agent
        )
        return await self.record_change(change)

    async def record_config_reload(self, config_key: str = None, changed_by: str = "system") -> bool:
        """
        记录配置重载

        Args:
            config_key: 配置键名（None表示重载所有配置）
            changed_by: 操作人

        Returns:
            bool: 记录是否成功
        """
        from datetime import datetime

        try:
            if config_key:
                # 记录单个配置重载
                query = """
                    SELECT id FROM config_items WHERE key_name = %s
                """
                result = await self.db_manager.execute_query_one(query, (config_key,))
                if result:
                    insert_query = """
                        INSERT INTO config_history (
                            config_key, config_id, old_value, new_value,
                            change_type, changed_by, change_reason, created_at
                        ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
                    """

                    await self.db_manager.execute_insert(insert_query, (
                        config_key,
                        result['id'],
                        None,
                        None,
                        ConfigChangeType.RELOAD.value,
                        changed_by,
                        "Reload configuration",
                        datetime.now()
                    ))

                    self.logger.info(f"Config reload recorded for {config_key} by {changed_by}")
                    return True
            else:
                # 记录全局配置重载
                insert_query = """
                    INSERT INTO config_history (
                        config_key, config_id, old_value, new_value,
                        change_type, changed_by, change_reason, created_at
                    ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
                """

                await self.db_manager.execute_insert(insert_query, (
                    "ALL_CONFIGS",
                    0,
                    None,
                    None,
                    ConfigChangeType.RELOAD.value,
                    changed_by,
                    "Reload all configurations",
                    datetime.now()
                ))

                self.logger.info(f"Global config reload recorded by {changed_by}")
                return True

        except Exception as e:
            self.logger.error(f"Failed to record config reload: {e}")
            return False

    async def record_service_restart(self, changed_by: str = "system", reason: str = None) -> bool:
        """
        记录服务重启

        Args:
            changed_by: 操作人
            reason: 重启原因

        Returns:
            bool: 记录是否成功
        """
        # 直接插入数据库，而不是创建ConfigChange对象
        from datetime import datetime

        try:
            query = """
                INSERT INTO config_history (
                    config_key, config_id, old_value, new_value,
                    change_type, changed_by, change_reason, created_at
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
            """

            await self.db_manager.execute_insert(query, (
                "SERVICE_RESTART",
                0,
                None,
                None,
                ConfigChangeType.RESTART.value,
                changed_by,
                reason or "Service restart triggered",
                datetime.now()
            ))

            self.logger.info(f"Service restart recorded by {changed_by}")
            return True

        except Exception as e:
            self.logger.error(f"Failed to record service restart: {e}")
            return False

    async def get_config_history(self, config_key: str, limit: int = 50,
                                offset: int = 0) -> List[Dict]:
        """
        获取特定配置项的变更历史

        Args:
            config_key: 配置键名
            limit: 限制数量
            offset: 偏移量

        Returns:
            List[Dict]: 变更历史记录
        """
        try:
            query = """
                SELECT h.*, i.display_name
                FROM config_history h
                LEFT JOIN config_items i ON h.config_id = i.id
                WHERE h.config_key = %s
                ORDER BY h.created_at DESC
                LIMIT %s OFFSET %s
            """
            return await self.db_manager.execute_query(query, (config_key, limit, offset))

        except Exception as e:
            self.logger.error(f"Failed to get config history for {config_key}: {e}")
            return []

    async def get_config_history_count(self, config_key: str) -> int:
        """
        获取特定配置项的变更历史总数

        Args:
            config_key: 配置键名

        Returns:
            int: 变更历史总数
        """
        try:
            query = "SELECT COUNT(*) as count FROM config_history WHERE config_key = %s"
            result = await self.db_manager.execute_query_one(query, (config_key,))
            return result['count'] if result else 0

        except Exception as e:
            self.logger.error(f"Failed to get config history count for {config_key}: {e}")
            return 0

    async def get_all_history(self, change_type: ConfigChangeType = None,
                             limit: int = 100, offset: int = 0,
                             start_date: datetime = None,
                             end_date: datetime = None) -> List[Dict]:
        """
        获取所有配置变更历史

        Args:
            change_type: 变更类型过滤
            limit: 限制数量
            offset: 偏移量
            start_date: 开始日期
            end_date: 结束日期

        Returns:
            List[Dict]: 变更历史记录
        """
        try:
            where_conditions = []
            params = []

            if change_type:
                where_conditions.append("h.change_type = %s")
                params.append(change_type.value)

            if start_date:
                where_conditions.append("h.created_at >= %s")
                params.append(start_date)

            if end_date:
                where_conditions.append("h.created_at <= %s")
                params.append(end_date)

            where_clause = "WHERE " + " AND ".join(where_conditions) if where_conditions else ""

            query = f"""
                SELECT h.*, i.display_name
                FROM config_history h
                LEFT JOIN config_items i ON h.config_id = i.id
                {where_clause}
                ORDER BY h.created_at DESC
                LIMIT %s OFFSET %s
            """
            params.extend([limit, offset])

            return await self.db_manager.execute_query(query, tuple(params))

        except Exception as e:
            self.logger.error(f"Failed to get all config history: {e}")
            return []

    async def get_all_history_count(self, change_type: ConfigChangeType = None,
                                   start_date: datetime = None,
                                   end_date: datetime = None) -> int:
        """
        获取所有配置变更历史总数

        Args:
            change_type: 变更类型过滤
            start_date: 开始日期
            end_date: 结束日期

        Returns:
            int: 变更历史总数
        """
        try:
            where_conditions = []
            params = []

            if change_type:
                where_conditions.append("change_type = %s")
                params.append(change_type.value)

            if start_date:
                where_conditions.append("created_at >= %s")
                params.append(start_date)

            if end_date:
                where_conditions.append("created_at <= %s")
                params.append(end_date)

            where_clause = "WHERE " + " AND ".join(where_conditions) if where_conditions else ""

            query = f"SELECT COUNT(*) as count FROM config_history {where_clause}"
            result = await self.db_manager.execute_query_one(query, tuple(params))
            return result['count'] if result else 0

        except Exception as e:
            self.logger.error(f"Failed to get all config history count: {e}")
            return 0

    async def get_user_history(self, user: str, limit: int = 50,
                              offset: int = 0) -> List[Dict]:
        """
        获取特定用户的操作历史

        Args:
            user: 用户名
            limit: 限制数量
            offset: 偏移量

        Returns:
            List[Dict]: 用户操作历史
        """
        try:
            query = """
                SELECT h.*, i.display_name
                FROM config_history h
                LEFT JOIN config_items i ON h.config_id = i.id
                WHERE h.changed_by = %s
                ORDER BY h.created_at DESC
                LIMIT %s OFFSET %s
            """
            return await self.db_manager.execute_query(query, (user, limit, offset))

        except Exception as e:
            self.logger.error(f"Failed to get user history for {user}: {e}")
            return []

    async def get_recent_changes(self, hours: int = 24, limit: int = 50) -> List[Dict]:
        """
        获取最近的配置变更

        Args:
            hours: 小时数
            limit: 限制数量

        Returns:
            List[Dict]: 最近的变更记录
        """
        try:
            query = """
                SELECT h.*, i.display_name
                FROM config_history h
                LEFT JOIN config_items i ON h.config_id = i.id
                WHERE h.created_at >= DATE_SUB(NOW(), INTERVAL %s HOUR)
                ORDER BY h.created_at DESC
                LIMIT %s
            """
            return await self.db_manager.execute_query(query, (hours, limit))

        except Exception as e:
            self.logger.error(f"Failed to get recent changes: {e}")
            return []

    async def get_change_statistics(self, days: int = 30) -> Dict[str, Any]:
        """
        获取变更统计信息

        Args:
            days: 统计天数

        Returns:
            Dict[str, Any]: 统计信息
        """
        try:
            stats = {}

            # 总变更数
            total_query = """
                SELECT COUNT(*) as count
                FROM config_history
                WHERE created_at >= DATE_SUB(NOW(), INTERVAL %s DAY)
            """
            total_result = await self.db_manager.execute_query_one(total_query, (days,))
            stats['total_changes'] = total_result['count'] if total_result else 0

            # 按变更类型统计
            type_query = """
                SELECT change_type, COUNT(*) as count
                FROM config_history
                WHERE created_at >= DATE_SUB(NOW(), INTERVAL %s DAY)
                GROUP BY change_type
            """
            type_results = await self.db_manager.execute_query(type_query, (days,))
            stats['by_type'] = {result['change_type']: result['count'] for result in type_results}

            # 按用户统计
            user_query = """
                SELECT changed_by, COUNT(*) as count
                FROM config_history
                WHERE created_at >= DATE_SUB(NOW(), INTERVAL %s DAY)
                GROUP BY changed_by
                ORDER BY count DESC
                LIMIT 10
            """
            user_results = await self.db_manager.execute_query(user_query, (days,))
            stats['by_user'] = {result['changed_by']: result['count'] for result in user_results}

            # 最常变更的配置
            config_query = """
                SELECT config_key, COUNT(*) as count
                FROM config_history
                WHERE created_at >= DATE_SUB(NOW(), INTERVAL %s DAY)
                  AND config_key NOT IN ('ALL_CONFIGS', 'SERVICE_RESTART')
                GROUP BY config_key
                ORDER BY count DESC
                LIMIT 10
            """
            config_results = await self.db_manager.execute_query(config_query, (days,))
            stats['frequently_changed'] = {result['config_key']: result['count'] for result in config_results}

            return stats

        except Exception as e:
            self.logger.error(f"Failed to get change statistics: {e}")
            return {}

    async def cleanup_old_history(self, days: int = 90) -> int:
        """
        清理旧的历史记录

        Args:
            days: 保留天数

        Returns:
            int: 清理的记录数
        """
        try:
            query = """
                DELETE FROM config_history
                WHERE created_at < DATE_SUB(NOW(), INTERVAL %s DAY)
            """
            deleted_count = await self.db_manager.execute_update(query, (days,))
            self.logger.info(f"Cleaned up {deleted_count} old config history records")
            return deleted_count

        except Exception as e:
            self.logger.error(f"Failed to cleanup old history: {e}")
            return 0

    async def export_history(self, config_key: str = None,
                           start_date: datetime = None,
                           end_date: datetime = None,
                           format: str = 'json') -> str:
        """
        导出历史记录

        Args:
            config_key: 配置键名（可选）
            start_date: 开始日期（可选）
            end_date: 结束日期（可选）
            format: 导出格式（json/csv）

        Returns:
            str: 导出的数据
        """
        try:
            # 构建查询条件
            where_conditions = []
            params = []

            if config_key:
                where_conditions.append("config_key = %s")
                params.append(config_key)

            if start_date:
                where_conditions.append("created_at >= %s")
                params.append(start_date)

            if end_date:
                where_conditions.append("created_at <= %s")
                params.append(end_date)

            where_clause = "WHERE " + " AND ".join(where_conditions) if where_conditions else ""

            query = f"""
                SELECT config_key, old_value, new_value, change_type,
                       changed_by, change_reason, ip_address, created_at
                FROM config_history
                {where_clause}
                ORDER BY created_at DESC
            """

            records = await self.db_manager.execute_query(query, tuple(params))

            if format.lower() == 'csv':
                return self._format_as_csv(records)
            else:
                return self._format_as_json(records)

        except Exception as e:
            self.logger.error(f"Failed to export history: {e}")
            return ""

    def _format_as_json(self, records: List[Dict]) -> str:
        """格式化为JSON"""
        import json
        return json.dumps(records, indent=2, default=str, ensure_ascii=False)

    def _format_as_csv(self, records: List[Dict]) -> str:
        """格式化为CSV"""
        import csv
        import io

        if not records:
            return ""

        output = io.StringIO()
        writer = csv.writer(output)

        # 写入表头
        headers = records[0].keys()
        writer.writerow(headers)

        # 写入数据
        for record in records:
            writer.writerow(record.values())

        return output.getvalue()

    async def rollback_config(self, config_key: str, history_id: int,
                             changed_by: str = "system") -> bool:
        """
        回滚配置到指定历史版本

        Args:
            config_key: 配置键名
            history_id: 历史记录ID
            changed_by: 操作人

        Returns:
            bool: 回滚是否成功
        """
        try:
            # 获取历史记录
            history_query = """
                SELECT * FROM config_history WHERE id = %s AND config_key = %s
            """
            history_record = await self.db_manager.execute_query_one(history_query, (history_id, config_key))

            if not history_record:
                self.logger.error(f"History record not found: {history_id}")
                return False

            # 获取配置项ID
            config_query = """
                SELECT id FROM config_items WHERE key_name = %s
            """
            config_result = await self.db_manager.execute_query_one(config_query, (config_key,))
            if not config_result:
                self.logger.error(f"Config item not found: {config_key}")
                return False

            # 更新配置值
            update_query = """
                UPDATE config_items
                SET current_value = %s, updated_at = CURRENT_TIMESTAMP
                WHERE key_name = %s
            """
            update_success = await self.db_manager.execute_update(
                update_query, (history_record['old_value'], config_key)
            ) > 0

            if update_success:
                # 记录回滚操作
                rollback_change = ConfigChange(
                    config_key=config_key,
                    config_id=config_result['id'],
                    old_value=history_record['new_value'],
                    new_value=history_record['old_value'],
                    change_type=ConfigChangeType.UPDATE,
                    changed_by=changed_by,
                    change_reason=f"Rollback to history ID: {history_id}"
                )
                await self.record_change(rollback_change)

                self.logger.info(f"Successfully rolled back config {config_key} to history {history_id}")
                return True

        except Exception as e:
            self.logger.error(f"Failed to rollback config {config_key}: {e}")

        return False